﻿using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;

namespace Rail.Commons.SerializeHelper
{
    /// <summary>
    /// 二进制序列化和反序列化
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BinaryFormatterHelper
    {
        private BinaryFormatterHelper()
        {
        }

        #region 序列化

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Byte[] Serialize<T>(T obj) where T : class
        {
            try
            {
                //创建内存流
                MemoryStream ms = new MemoryStream();
                //产生二进制序列化格式
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, obj);
                ms.Position = 0;
                byte[] buffers = ms.ToArray();
                //清空和释放内存流
                ms.Close();
                ms.Dispose();
                return Compress(buffers);
            }
            catch
            {
                return new byte[] { };
            }
        }

        /// <summary>
        /// 压缩数据
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static byte[] Compress(byte[] buffer)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return buffer;
            }
            //创建内存流
            MemoryStream ms = new MemoryStream();
            //压缩和解压缩流
            GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true);
            gzip.Write(buffer, 0, buffer.Length);
            //清空和释放压缩和解压缩流
            gzip.Close();
            gzip.Dispose();
            ms.Position = 0;
            byte[] returnBuffer = new byte[ms.Length];
            ms.Read(returnBuffer, 0, int.Parse(ms.Length.ToString()));
            //清空和释放内存流
            ms.Close();
            ms.Dispose();
            return returnBuffer;
        }

        #endregion 序列化

        #region 反序列化

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static T Deserilize<T>(byte[] buffer) where T : class
        {
            try
            {
                byte[] debuffer = Decompress(buffer);
                //产生二进制序列化格式
                BinaryFormatter bf = new BinaryFormatter();
                //创建内存流
                MemoryStream ms = new MemoryStream(debuffer);
                ms.Position = 0;
                T obj = bf.Deserialize(ms) as T;
                //清空和释放内存流
                ms.Close();
                ms.Dispose();
                return obj;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 解压缩流
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static byte[] Decompress(byte[] buffer)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return buffer;
            }
            try
            {
                //创建内存流
                MemoryStream ms = new MemoryStream(buffer);
                ms.Position = 0;
                //压缩和解压缩流
                GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
                byte[] rebuffer = new byte[1024];
                //创建内存流
                MemoryStream msre = new MemoryStream();
                while (true)
                {
                    int readcount = gzip.Read(rebuffer, 0, rebuffer.Length);
                    if (readcount > 0)
                        msre.Write(rebuffer, 0, readcount);
                    else
                        break;
                }
                msre.Close();
                byte[] buffers = msre.ToArray();
                msre.Dispose();
                //清空和释放压缩和解压缩流
                gzip.Close();
                gzip.Dispose();
                //清空和释放内存流
                ms.Close();
                ms.Dispose();
                return buffers;
            }
            catch
            {
                return new byte[] { };
            }
        }

        #endregion 反序列化
    }
}